package com.chaos.framework.starter.config;

import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.chaos.framework.model.dto.result.Result;
import com.chaos.framework.model.enums.ResultEnum;
import com.chaos.framework.model.exception.BusinessException;
import feign.FeignException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.authentication.AccountStatusException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.stream.Collectors;

/**
 * @author Jacky
 */
@Order(2)
@ControllerAdvice
@Slf4j
public class GlobalDefultExceptionHandler {


    @ResponseBody
    @ExceptionHandler(IllegalArgumentException.class)
    public Result illegalArgumentException(IllegalArgumentException e) {
        Result result = Result.of(ResultEnum.ILLEGAL_ARGUMENT.getCode(), e.getMessage());
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), e.getMessage());
        return result;
    }

    @ResponseBody
    @ExceptionHandler(InvalidFormatException.class)
    public Result invalidFormatException(InvalidFormatException e) {
        Result result = Result.of(ResultEnum.INVALID_FORMAT.getCode(), e.getMessage());
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), e.getMessage());
        return result;
    }

    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result methodArgumentNotValidException(MethodArgumentNotValidException e) {
        Result result = Result.of(ResultEnum.METHOD_ARGUMENT_NOT_VALID);
        String errorMsg = e.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.joining(" | "));
        result.setMsg(errorMsg);
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), result.getMsg());
        return result;
    }

    @ResponseBody
    @ExceptionHandler(DuplicateKeyException.class)
    public Result duplicateException(DuplicateKeyException e) {
        Result result = Result.of(ResultEnum.SQL_DUPLICATE_KEY);
        result.setMsg(ResultEnum.SQL_DUPLICATE_KEY.getDefaultMsg());
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), result.getMsg());
        return result;
    }

    @ResponseBody
    @ExceptionHandler(DataIntegrityViolationException.class)
    public Result dataIntegrityViolationException(DataIntegrityViolationException e) {
        Result result = Result.of(ResultEnum.SQL_DATA_INTEGRITY_VIOLATION);
        result.setMsg(ResultEnum.SQL_DATA_INTEGRITY_VIOLATION.getDefaultMsg());
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), result.getMsg());
        return result;
    }

    @ResponseBody
    @ExceptionHandler(BusinessException.class)
    public Result businessException(BusinessException e) {
        Result result = e.getResult();
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), result.getMsg());
        return result;
    }

    @ResponseBody
    @ExceptionHandler(FeignException.class)
    public Result feignException(FeignException e) {
        Result result = Result.of(ResultEnum.SERVICE_UNAVAILABLE);
        log.warn("[框架]: 业务异常编码[{}],错误信息[{}]", result.getCode(), e.getMessage());
        return result;
    }

    @ExceptionHandler(InsufficientAuthenticationException.class)
    public void handleError(InsufficientAuthenticationException e) {
        throw e;
    }

    @ResponseBody
    @ExceptionHandler(Exception.class)
    public Result defultExcepitonHandler(Exception e) {
        Result result = Result.unknow();
        log.error("错误编码[{}],错误信息[{}]", result.getCode(), result.getMsg(), e);
        e.printStackTrace();
        return result;
    }
}

